package com.jn.erp.web.api.course.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jn.erp.utils.DateUtils;
import com.jn.erp.utils.RedisLock;
import com.jn.erp.web.api.course.entity.TCourseOrder;
import com.jn.erp.web.api.course.entity.TCourseOrderConfig;
import com.jn.erp.web.api.course.mapper.TCourseOrderConfigMapper;
import com.jn.erp.web.api.course.service.TCourseOrderService;
import com.jn.erp.web.api.student.entity.TStudentClassRela;
import com.jn.erp.web.api.student.mapper.TStudentClassRelaMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 周期性创建课程记录-每月执行一次，创建近90天的课程记录，在排课配置新建时初始化
 * */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class TCourseOrderTask {
    @Autowired
    private RedisLock redisLock;

    @Autowired
    private  TCourseOrderConfigMapper tCourseOrderConfigMapper;

    @Autowired
    private TCourseOrderService tCourseOrderService;

    @Autowired
    private TStudentClassRelaMapper tStudentClassRelaMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    //每天21:00运行
    @Scheduled(cron = "0 0 21 * * ?")
    public void createCourseOrder() {
        log.info("----------------------------  createCourseOrder   start --------------------------------------");
        Boolean idxScoreReportsTask = redisLock.lock("TCourseOrderTask:createCourseOrder");
        if(!idxScoreReportsTask){
            return;
        }
        //可能存在Redis容灾不生效的的情况取数据库数据进行初始化
        initOrderNo();

        try {
            List<TCourseOrderConfig> tCourseOrderConfigs = tCourseOrderConfigMapper.selectList(new QueryWrapper<TCourseOrderConfig>().eq("is_delete", 0)
                    .ge("end_time", new Date()));
            if(CollectionUtils.isEmpty(tCourseOrderConfigs)){
                log.info("无需有效排课配置，无需进行排课");
                return;
            }
            for(TCourseOrderConfig tCourseOrderConfig:tCourseOrderConfigs){
                List<String> orderNoList = new ArrayList<>();
    //            排课方式,1规律2日历
                switch (tCourseOrderConfig.getType()){
                    //循环方式1每天2每周
                    case 1:{
                        switch (tCourseOrderConfig.getCirculateType()){
                            case 1 :{
                                LocalDateTime last90Date = LocalDateTime.now().plusDays(90);
                                if(tCourseOrderConfig.getEndTime().compareTo(DateUtils.getString(last90Date,"yyyy-MM-dd HH:mm:ss")) <= 0){
                                    last90Date = DateUtils.getLocalDateTime(tCourseOrderConfig.getEndTime(),"yyyy-MM-dd HH:mm:ss");
                                    //因为endtime为00:00:00往后取一天
                                    last90Date = last90Date.plusDays(1);
                                }
                                List<TStudentClassRela> tStudentClassRelas = tStudentClassRelaMapper.selectList(new QueryWrapper<TStudentClassRela>().eq("deleted", 0).eq("class_id", tCourseOrderConfig.getClassId()));
                                List<TCourseOrder> tCourseOrders = new ArrayList<>();
                                for(TStudentClassRela tStudentClassRela : tStudentClassRelas) {
                                    LocalDateTime startTime = DateUtils.getLocalDateTime(tCourseOrderConfig.getStartTime(),"yyyy-MM-dd HH:mm:ss").compareTo(LocalDateTime.now()) >= 0 ? DateUtils.getLocalDateTime(tCourseOrderConfig.getStartTime(),"yyyy-MM-dd HH:mm:ss") : LocalDateTime.now();
                                    TCourseOrder lastCourseOrder = tCourseOrderService.lastCourseOrder(startTime,tCourseOrderConfig.getId(),tStudentClassRela.getStudentId());
                                    if (!Objects.isNull(lastCourseOrder)) {
                                        startTime = lastCourseOrder.getClassDate().plusDays(1);
                                    }
                                    //当日大于开课时间不在创建当日课程----待补充

                                    int step = 0;
                                    while (startTime.compareTo(last90Date) <= 0) {
                                        String orderNo = "";
                                        if(!CollectionUtils.isEmpty(orderNoList)){
                                            LocalDateTime finalStartTime = startTime;
                                            List<String> orderNos = orderNoList.stream().filter(u -> u.contains(DateUtils.getString(finalStartTime, "yyyyMMdd"))).collect(Collectors.toList());
                                            if(!CollectionUtils.isEmpty(orderNos)){
                                                orderNo = orderNos.get(0);
                                            }else{
                                                orderNo = getOrderNo(startTime, "courseOrderNo",tCourseOrderConfig.getId());
                                                orderNoList.add(orderNo);
                                            }
                                        }else{
                                            orderNo = getOrderNo(startTime, "courseOrderNo",tCourseOrderConfig.getId());
                                            orderNoList.add(orderNo);
                                        }
                                        //判断当天课次是否已点过名，点过不再重新生成
                                        if(step == 0){
                                           int called = tCourseOrderService.called(orderNo);
                                           if(called >0){
                                               startTime = startTime.plusDays(1);
                                               step += 1;
                                               continue;
                                           }
                                        }
                                        TCourseOrder courseOrder = new TCourseOrder(tCourseOrderConfig.getOrgId(), tCourseOrderConfig.getId(),orderNo, 1, tStudentClassRela.getConsumeCourseId(), tCourseOrderConfig.getClassId()
                                                , startTime, tCourseOrderConfig.getClassStartTime(), tCourseOrderConfig.getClassEndTime(), null, tStudentClassRela.getStudentId()
                                                , tCourseOrderConfig.getTeacher(), tCourseOrderConfig.getAssistant(), tCourseOrderConfig.getClassRoom(),tCourseOrderConfig.getDescription(), "1", tCourseOrderConfig.getClassHour(), 0, null, null
                                                ,1,null, LocalDateTime.now(), "sys", LocalDateTime.now(), "sys", "0");

                                        tCourseOrders.add(courseOrder);
                                        startTime = startTime.plusDays(1);
                                        step += 1;
                                    }

                                }
                                tCourseOrderService.saveBatch(tCourseOrders);
                                break;
                            }
                            case 2 :{
                                LocalDateTime last90Date = LocalDateTime.now().plusDays(90);
                                if(tCourseOrderConfig.getEndTime().compareTo(DateUtils.getString(last90Date,"yyyy-MM-dd HH:mm:ss")) <= 0){
                                    last90Date = DateUtils.getLocalDateTime(tCourseOrderConfig.getEndTime(),"yyyy-MM-dd HH:mm:ss");
                                    //因为endtime为00:00:00往后取一天
                                    last90Date = last90Date.plusDays(1);
                                }
                                List<TStudentClassRela> tStudentClassRelas = tStudentClassRelaMapper.selectList(new QueryWrapper<TStudentClassRela>().eq("deleted", 0).eq("class_id", tCourseOrderConfig.getClassId()));
                                List<TCourseOrder> tCourseOrders = new ArrayList<>();
                                for(TStudentClassRela tStudentClassRela : tStudentClassRelas) {
                                    LocalDateTime startTime = DateUtils.getLocalDateTime(tCourseOrderConfig.getStartTime(),"yyyy-MM-dd HH:mm:ss").compareTo(LocalDateTime.now()) >= 0 ? DateUtils.getLocalDateTime(tCourseOrderConfig.getStartTime(),"yyyy-MM-dd HH:mm:ss") : LocalDateTime.now();
                                    TCourseOrder lastCourseOrder = tCourseOrderService.lastCourseOrder(startTime,tCourseOrderConfig.getId(),tStudentClassRela.getStudentId());
                                    if (!Objects.isNull(lastCourseOrder)) {
                                        startTime = lastCourseOrder.getClassDate().plusDays(1);
                                    }
                                    int startWeekNum = startTime.getDayOfWeek().getValue();
                                    int temp = tCourseOrderConfig.getWeekNum() - startWeekNum;
                                    temp = temp == 0 ? 0 : temp > 0 ? temp : temp +7;
                                    startTime = startTime.plusDays(temp);
                                    int step = 0;
                                    while (startTime.compareTo(last90Date) <= 0) {
                                        String orderNo = "";
                                        if(!CollectionUtils.isEmpty(orderNoList)){
                                            LocalDateTime finalStartTime = startTime;
                                            List<String> orderNos = orderNoList.stream().filter(u -> u.contains(DateUtils.getString(finalStartTime, "yyyyMMdd"))).collect(Collectors.toList());
                                            if(!CollectionUtils.isEmpty(orderNos)){
                                                orderNo = orderNos.get(0);
                                            }else{
                                                orderNo = getOrderNo(startTime, "courseOrderNo",tCourseOrderConfig.getId());
                                                orderNoList.add(orderNo);
                                            }
                                        }else{
                                            orderNo = getOrderNo(startTime, "courseOrderNo",tCourseOrderConfig.getId());
                                            orderNoList.add(orderNo);
                                        }

                                        //判断当天课次是否已点过名，点过不再重新生成
                                        if(step == 0){
                                            int called = tCourseOrderService.called(orderNo);
                                            if(called >0){
                                                startTime = startTime.plusDays(7);
                                                step += 1;
                                                continue;
                                            }
                                        }
                                        TCourseOrder courseOrder = new TCourseOrder(tCourseOrderConfig.getOrgId(), tCourseOrderConfig.getId(),orderNo, 1, tStudentClassRela.getConsumeCourseId(), tCourseOrderConfig.getClassId()
                                                , startTime, tCourseOrderConfig.getClassStartTime(), tCourseOrderConfig.getClassEndTime(),tCourseOrderConfig.getWeekNum(),tStudentClassRela.getStudentId()
                                                , tCourseOrderConfig.getTeacher(), tCourseOrderConfig.getAssistant(), tCourseOrderConfig.getClassRoom(),tCourseOrderConfig.getDescription(), "1", tCourseOrderConfig.getClassHour(), 0, null, null
                                                ,1, null,LocalDateTime.now(), "sys", LocalDateTime.now(), "sys", "0");

                                        tCourseOrders.add(courseOrder);
                                        startTime = startTime.plusDays(7);
                                        step += 1;
                                    }

                                }
                                tCourseOrderService.saveBatch(tCourseOrders);
                                break;
                            }
                        }
                        break;
                    }
                    //日历排课
                    case 2:{
                        String[] classDates = tCourseOrderConfig.getClassDate().split(",");
                        List<TStudentClassRela> tStudentClassRelas = tStudentClassRelaMapper.selectList(new QueryWrapper<TStudentClassRela>().eq("deleted", 0).eq("class_id", tCourseOrderConfig.getClassId()));
                        List<TCourseOrder> tCourseOrders = new ArrayList<>();
                        for(String classDate : classDates){
                            String orderNo = getOrderNo(DateUtils.getLocalDateTime(classDate, "yyyy-MM-dd"), "courseOrderNo",tCourseOrderConfig.getId());
                            for(TStudentClassRela tStudentClassRela : tStudentClassRelas){
                                List<TCourseOrder> tCourseOrderList = tCourseOrderService.list(new QueryWrapper<TCourseOrder>().eq("cof_id", tCourseOrderConfig.getId()).eq("student_id", tStudentClassRela.getStudentId()).eq("DATE_FORMAT( class_date, '%Y-%m-%d' )",classDate).eq("is_delete", "0"));
                               if(!CollectionUtils.isEmpty(tCourseOrderList)){
                                   continue;
                               }
                                TCourseOrder courseOrder = new TCourseOrder(tCourseOrderConfig.getOrgId(),tCourseOrderConfig.getId(),orderNo,1,tStudentClassRela.getConsumeCourseId(),tCourseOrderConfig.getClassId()
                                        , DateUtils.getLocalDateTime(classDate,"yyyy-MM-dd"),tCourseOrderConfig.getClassStartTime(),tCourseOrderConfig.getClassEndTime(), null,tStudentClassRela.getStudentId()
                                        ,tCourseOrderConfig.getTeacher(),tCourseOrderConfig.getAssistant(),tCourseOrderConfig.getClassRoom(),tCourseOrderConfig.getDescription(),"1",tCourseOrderConfig.getClassHour(),0,null,null
                                        ,1,null, LocalDateTime.now(),"sys",LocalDateTime.now(),"sys","0");
                                List<TCourseOrder> list = tCourseOrderService.list(new QueryWrapper<TCourseOrder>().eq("cof_id", tCourseOrderConfig.getId()).eq("student_id", tStudentClassRela.getStudentId())
                                        .eq("DATE_FORMAT( class_date, '%Y-%m-%d' )", classDate).eq("is_delete", "0"));
                                if(CollectionUtils.isEmpty(list)){
                                    tCourseOrders.add(courseOrder);
                                }
                            }
                        }
                        tCourseOrderService.saveBatch(tCourseOrders);
                        break;
                    }
                }

            }
            log.info("---------------------------- Create createCourseOrder   end --------------------------------------");
        } catch (Exception e) {
            System.out.println("TCourseOrderTask=====>>>>>"+e.getMessage());
            log.info(e.getMessage());
            e.printStackTrace();
        }finally {
            redisLock.del("TCourseOrderTask:createCourseOrder");
        }

    }

    public void initOrderNo(){
        //可能存在Redis容灾不生效的的情况取数据库数据进行初始化
        LocalDateTime eDate = LocalDateTime.now().plusDays(90);
        LocalDateTime sDate = LocalDateTime.now();
        while(sDate.compareTo(eDate) <= 0){
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(DateUtils.getString(sDate,"yyyyMMdd"));
            String key = "courseOrderNo"+":"+stringBuffer.toString();
            Boolean b = redisTemplate.hasKey(key);
            if(!b){
                String orderNo = tCourseOrderService.getMaxOrderNo(DateUtils.getString(sDate, "yyyyMMdd"));
                if(StringUtils.isNotBlank(orderNo)){
                    orderNo = orderNo.substring(orderNo.length()-4,orderNo.length());
                    redisTemplate.opsForValue().set(key,Integer.parseInt(orderNo));
                }
            }
            sDate = sDate.plusDays(1);
        }
    }
    public String getOrderNo(LocalDateTime classDate ,String keyHead ,Long cofId){
        String classDateStr = DateUtils.getString(classDate, "yyyy-MM-dd");
        List<TCourseOrder> list = tCourseOrderService.list(new QueryWrapper<TCourseOrder>().eq("is_delete", "0").eq("cof_id", cofId).eq("DATE_FORMAT( class_date, '%Y-%m-%d' )",classDateStr));
        if(!CollectionUtils.isEmpty(list)){
            return list.get(0).getOrderNo();
        }
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(DateUtils.getString(classDate,"yyyyMMdd"));
        String key = keyHead+":"+stringBuffer.toString();
        //这里是 Redis key的前缀，如: sys:日期
        Long autoID = redisTemplate.opsForValue().increment(key, 1);
        // 设置key过期时间, 保证每天的流水号从1开始
//        if (autoID == 1) {
//            redisTemplate.expire(key, 1, TimeUnit.DAYS);
//        }
        if(autoID<10000){
            String num = StringUtils.leftPad(String.valueOf(autoID), 4, "0");
            stringBuffer.append(num);
            return stringBuffer.toString();
        } else {
            throw  new RuntimeException("当日课程编号已取完！");
        }
    }


    public String getOrderNo1(LocalDateTime classDate ,String keyHead ,Long cofId){
        String classDateStr = DateUtils.getString(classDate, "yyyy-MM-dd");
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(DateUtils.getString(classDate,"yyyyMMdd"));
        String key = keyHead+":"+stringBuffer.toString();
        //这里是 Redis key的前缀，如: sys:日期
        Long autoID = redisTemplate.opsForValue().increment(key, 1);
        // 设置key过期时间, 保证每天的流水号从1开始
//        if (autoID == 1) {
//            redisTemplate.expire(key, 1, TimeUnit.DAYS);
//        }
        if(autoID<10000){
            String num = StringUtils.leftPad(String.valueOf(autoID), 4, "0");
            stringBuffer.append(num);
            return stringBuffer.toString();
        } else {
            throw  new RuntimeException("当日课程编号已取完！");
        }
    }
}
